#include <stdio.h>
#include <stdbool.h> 
int count = 0; // 记录状态的数量
bool IsSafe(int now[]) {
    // 检查狼会不会吃掉鸡
    if ((now[1] == now[2]) && (now[0] != now[1]))
        return false;
    // 检查鸡会不会吃掉谷子
    if ((now[2] == now[3]) && (now[0] != now[2]))
        return false;
    return true;
}
 
// 备忘录函数，检查当前状态是否已经出现过
bool isRepeated(int now[], int dira[], int a, int step) {
    for (int i = 0; i < step; i++) {
        if (dira[i] == a) {
            return true;
        }
    }
    return false;
}
 
void display(int dira[]){
	for(int i=0;i<=17;i++){
		printf("%2d",dira[i]);
	}
	printf("\n");
}

void path(int dira[]) {
    int i = 0;
    while (dira[i] != 0) {
        switch (dira[i] - dira[i + 1]) {
            case 8:
            case -8:
                printf("农夫独自过河\n");
                break;
            case 12:
            case -12:
                printf("农夫带狼过河\n");
                break;
            case 10:
            case -10:
                printf("农夫带鸡过河\n");
                break;
            case 9:
            case -9:
                printf("农夫带谷子过河\n");
                break;
            default:
                printf("未知动作\n");
                break;
        }
        i++;
    }
}
// 回溯法函数
void backtracking(int now[],int dira[],int step) {
    //剪枝 

    int a = now[0] * 8 + now[1] * 4 + now[2] * 2 + now[3] * 1;
    
    if (isRepeated(now,dira,a,step) || !IsSafe(now)) {
        return;
    }
	dira[step]=a;   

    if (now[0] == 0 && now[1] == 0 && now[2] == 0 && now[3] == 0) {
        count++;
        printf("过河的第%d的方法\n",count);
//        display(dira);
        path(dira);
        printf("\n");
        return;
    }
 
    // 尝试每种可能的移动方式
    for (int i = 0; i < 4; i++) {
        if (now[i] == now[0]) { // 物体和农夫在同一侧
            int temp[4];
            for (int j = 0; j < 4; j++) {
                temp[j] = now[j]; // 备份当前状态
            }
 
            now[i] = !now[i]; // 移动物体
            if(i!=0){
            now[0] = !now[0]; // 移动农夫
            }
            backtracking(now,dira,step+1); // 递归调用
            for (int j = 0; j < 4; j++) {
                now[j] = temp[j]; // 恢复当前状态
            }
        }
    }
}
 
int main() {
    int now[4] = {1, 1, 1, 1}; // 农夫、狼、鸡、谷子的初始位置都在河的一侧
	int dira[18];
	for(int i=0;i<18;i++){
		dira[i]=0;
	}
    backtracking(now,dira,0); // 调用回溯法函数
    return 0;
}
